package org.mspring.mlog.web.blog;

import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.TermQuery;
import org.mspring.mlog.BlogUtils;
import org.mspring.mlog.biz.ArticleViewCountService;
import org.mspring.mlog.cache.ArticleCacheService;
import org.mspring.mlog.common.ArticleDto;
import org.mspring.mlog.entity.ArticleEntity;
import org.mspring.mlog.entity.CategoryEntity;
import org.mspring.mlog.entity.TagEntity;
import org.mspring.mlog.common.constants.ArticleStatus;
import org.mspring.mlog.search.ArticleSearchEntity;
import org.mspring.mlog.search.ArticleSearchService;
import org.mspring.mlog.service.ArticleEntityService;
import org.mspring.mlog.service.CategoryEntityService;
import org.mspring.mlog.service.TagEntityService;
import org.mspring.mlog.support.ServiceContext;
import org.mspring.nbee.common.PageResult;
import org.mspring.nbee.common.Pager;
import org.mspring.nbee.web.support.WebContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * @author Gao Youbo
 * @since 2015-01-11 12:43
 */
@Controller("blogArticleAction")
public class ArticleController {
    private static final Logger LOG = LoggerFactory.getLogger(ArticleController.class);

    private ArticleEntityService articleEntityService;
    private CategoryEntityService categoryEntityService;
    private TagEntityService tagEntityService;
    private ArticleViewCountService articleViewCountService;
    private ArticleCacheService articleCacheService;
    private ArticleSearchService articleSearchService;
    private ServiceContext serviceContext;

    @RequestMapping("/article/{id:\\d+}")
    public String view(@PathVariable long id, WebContext context, Model model) throws IOException {
        if (id <= 0) {
            context.getResponse().sendError(404);
        }
        ArticleEntity article = articleCacheService.getArticle(id);
        if (article == null || article.getStatus() != ArticleStatus.NORMAL) {
            context.getResponse().sendError(404);
        }
        model.addAttribute("article", ArticleDto.fromArticle(article, serviceContext));
        articleViewCountService.increment(article.getId());
        BlogUtils.setSiteTitle(article.getTitle(), model);
        return "/blog/article";
    }


    @RequestMapping("/search")
    public String search(WebContext context, Model model) {
        Pager pager = context.getPager();

        String searchText = context.getParam("searchText");

        if (StringUtils.isNotBlank(searchText)) {
            BooleanQuery query = new BooleanQuery.Builder()
                    .add(new TermQuery(new Term("content", searchText)), BooleanClause.Occur.SHOULD)
                    .add(new TermQuery(new Term("title", searchText)), BooleanClause.Occur.SHOULD)
                    .build();

            PageResult<ArticleSearchEntity> tempResult = articleSearchService.search(query, pager);

            List<ArticleEntity> articleList = new ArrayList<>();
            for (ArticleSearchEntity searchEntity : tempResult.getItemList()) {
                ArticleEntity article = articleCacheService.getArticle(searchEntity.getId());
                articleList.add(article);
            }

            PageResult<ArticleDto> articleResult = new PageResult<>();
            articleResult.setPager(tempResult.getPager());
            articleResult.setTotal(tempResult.getTotal());
            articleResult.setItemList(ArticleDto.fromArticles(articleList, serviceContext));
            model.addAttribute("articleResult", articleResult);
            model.addAttribute("searchText", searchText);
        }
        return "/blog/search";
    }

    /**
     * 根据分类归档
     *
     * @param categoryId
     * @param context
     * @param model
     * @return
     */
    @RequestMapping("/article/category/{categoryId:\\d+}")
    public String categoryArchivers(@PathVariable long categoryId, WebContext context, Model model) throws IOException {
        CategoryEntity category = categoryEntityService.findById(categoryId);
        if (category == null) {
            context.getResponse().sendError(404);
        }
        int page = context.getParamAsInt("page", 1);
        PageResult<Long> tempResult = articleEntityService.findArticleByCategory(categoryId, page);

        List<ArticleDto> itemList = Lists.newArrayList();
        for (Long id : tempResult.getItemList()) {
            ArticleEntity article = articleCacheService.getArticle(id);
            if (article == null) {
                continue;
            }
            itemList.add(ArticleDto.fromArticle(article, serviceContext));
        }

        PageResult<ArticleDto> articleResult = new PageResult<>();
        articleResult.setPager(tempResult.getPager());
        articleResult.setTotal(tempResult.getTotal());
        articleResult.setItemList(itemList);

        model.addAttribute("articleResult", articleResult);
        model.addAttribute("category", categoryId);
        BlogUtils.setSiteTitle("分类 - " + category.getName(), model);
        return "/blog/index";
    }

    /**
     * 根据标签归档
     *
     * @param tagId
     * @param context
     * @param model
     * @return
     */
    @RequestMapping("/article/tag/{tagId:\\d+}")
    public String tagArchivers(@PathVariable long tagId, WebContext context, Model model) throws IOException {
        TagEntity tag = tagEntityService.findById(tagId);
        if (tag == null) {
            context.getResponse().sendError(404);
        }
        int page = context.getParamAsInt("page", 1);
        PageResult<Long> tempResult = articleEntityService.findArticleByTag(tagId, page);

        List<ArticleDto> itemList = Lists.newArrayList();
        for (Long id : tempResult.getItemList()) {
            ArticleEntity article = articleCacheService.getArticle(id);
            if (article == null) {
                continue;
            }
            itemList.add(ArticleDto.fromArticle(article, serviceContext));
        }

        PageResult<ArticleDto> articleResult = new PageResult<>();
        articleResult.setPager(tempResult.getPager());
        articleResult.setTotal(tempResult.getTotal());
        articleResult.setItemList(itemList);

        model.addAttribute("articleResult", articleResult);
        model.addAttribute("tagId", tagId);
        BlogUtils.setSiteTitle("标签 - " + tag.getName(), model);
        return "/blog/index";
    }

    @Autowired
    public void setArticleEntityService(ArticleEntityService articleEntityService) {
        this.articleEntityService = articleEntityService;
    }

    @Autowired
    public void setCategoryEntityService(CategoryEntityService categoryEntityService) {
        this.categoryEntityService = categoryEntityService;
    }

    @Autowired
    public void setTagEntityService(TagEntityService tagEntityService) {
        this.tagEntityService = tagEntityService;
    }

    @Autowired
    public void setArticleViewCountService(ArticleViewCountService articleViewCountService) {
        this.articleViewCountService = articleViewCountService;
    }

    @Autowired
    public void setArticleCacheService(ArticleCacheService articleCacheService) {
        this.articleCacheService = articleCacheService;
    }

    @Autowired
    public void setArticleSearchService(ArticleSearchService articleSearchService) {
        this.articleSearchService = articleSearchService;
    }

    @Autowired
    public void setServiceContext(ServiceContext serviceContext) {
        this.serviceContext = serviceContext;
    }
}
